﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Threading;
using System.Web;
using System.Web.Mvc;
using TestOnlineProject.Models.Entities;
using TestOnlineProject.Models.BusinessLogic;
using PagedList;

namespace TestOnlineProject.Controllers
{
    [Authorize(Roles = "1")]
    public class UserController : Controller
    {
        UserBLO userBLO = new UserBLO();
        RoleBLO roleBLO = new RoleBLO();

        //
        // GET: /User/

        public ActionResult Index(int? page, string keyWord = "", string column = "", string sort = "")
        {
            try
            {
                // No. list.
                var noList = new List<NoModel>();

                // User list.
                List<User> users = userBLO.ToList(ref noList, page, keyWord, column, sort);

                // Sort states.
                ViewBag.KeyWord = keyWord;
                ViewBag.Page = page;
                ViewBag.Column = column;
                ViewBag.Sort = sort;
                ViewBag.NoList = noList;

                // Return.
                var pageNumber = page ?? 1;
                var onePageOfUsers = users.ToPagedList(pageNumber, 10);
                ViewBag.onePageOfUsers = onePageOfUsers;
                return Request.IsAjaxRequest()
                    ? (ActionResult) PartialView("_List")
                    : View();
            }
            catch (Exception)
            {
                // Wrtite to log file.
                return RedirectToAction("Index", "Error", new { Area = "" });
            }
        }

        //
        // GET: /User/Create

        public ActionResult Create()
        {
            try
            {
                //Get all role.
                var roles = roleBLO.ToList();
                ViewBag.RoleId = new SelectList(roles, "RoleId", "Name");
                return View();
            }
            catch (Exception)
            {
                // Write to log file.
                return RedirectToAction("Index", "Error", new { Area = "" });
            }
        }

        //
        // POST: /User/Create

        [HttpPost]
        public ActionResult Create(User user)
        {
            try
            {
                var roles = roleBLO.ToList();
                ViewBag.RoleId = new SelectList(roles, "RoleId", "Name", user.RoleId);

                if (ModelState.IsValid)
                {
                    // Get picture
                    var picture = Request.Files["FileUpload"];
                    if (picture != null)
                    {
                        if (picture.ContentLength > 0)
                        {
                            // Split to get name picture
                            var extension = picture.FileName.Split('.');
                            var nameOfPicture = user.Username + "." + extension[extension.Length - 1];

                            // Save picture
                            picture.SaveAs(HttpContext.Server.MapPath("~/Images/Profile/") + nameOfPicture);
                            user.ImageUrl = nameOfPicture;
                        }
                    }

                    // Add User to db
                    var result = userBLO.Add(user);

                    // Check exist username.
                    if (result == -1)
                    {
                        ModelState.AddModelError("", "Duplicate Username.");
                        return View(user);
                    }

                    // Check exist username.
                    if (result == -2)
                    {
                        ModelState.AddModelError("", "Duplicate E-Mail.");
                        return View(user);
                    }

                    // Send message to view notify that create successful.
                    if (result > 0)
                    {
                        TempData["Msg"] = "New user has been created.";
                        return RedirectToAction("Details", new { id = user.UserId });
                    }

                    ModelState.AddModelError("", "An error occurred.");
                }

                return View(user);
            }
            catch (Exception)
            {
                // Write to log file.
                return RedirectToAction("Index", "Error", new { Area = "" });
            }
        }

        //
        // GET: /User/Import

        public ActionResult Import()
        {
            return View();
        }

        //
        // PSOT: /User/Import

        [HttpPost]
        public JsonResult Import(HttpPostedFileBase file)
        {
            try
            {
                var fileUpload = Request.Files["FileUpload"];

                if (fileUpload != null && fileUpload.ContentLength > 0)
                {
                    string saveFile = "~/ResourceFiles/" + fileUpload.FileName;
                    fileUpload.SaveAs(Server.MapPath(saveFile));
                    string connectionString;
                    if (Path.GetExtension(fileUpload.FileName) == ".xlsx")
                    {
                        connectionString = string.Format("Provider=Microsoft.ACE.OLEDB.12.0;Data Source={0};Extended Properties=\"Excel 12.0 Xml; IMEX = 1\"",
                                      Server.MapPath(saveFile));
                    }
                    else if (Path.GetExtension(fileUpload.FileName) == ".xls")
                    {
                        connectionString = string.Format("Provider=Microsoft.Jet.OLEDB.4.0;Data Source={0};Extended Properties=\"Excel 8.0; IMEX =1\"",
                                      Server.MapPath(saveFile));
                    }
                    else
                    {
                        return new JsonResult
                            {
                                Data = new { success = false, error = "Please import by Excel Workbook file!" }
                            };
                    }

                    var tuple = userBLO.ParseFile(connectionString, Server.MapPath(saveFile));
                    var fatalError = tuple.Item4;
                    if (fatalError)
                    {
                        return new JsonResult()
                            {
                                Data = new { success = false, error = "Please download template to have an exactly format." }
                            };
                    }

                    Session["ListUser"] = tuple.Item1;
                    Session["numSuccess"] = tuple.Item2;
                    Session["numFail"] = tuple.Item3;
                    if (tuple.Item5)
                    {
                        return new JsonResult()
                        {
                            Data = new { success = true, error = "Out of time! Please separate your file to import faster!" }
                        };
                    }
                    return new JsonResult()
                        {
                            Data = new { success = true, error = "" }
                        };
                }
                return new JsonResult()
                    {
                        Data = new { success = false, error = "Please select the file." }
                    };
            }
            catch (Exception e)
            {
                // Write to log file.
                return new JsonResult()
                    {
                        Data = new { success = false, error = e.Message }
                    };
            }
        }

        //
        // GET: /User/Edit

        public ActionResult Edit(int id = 0)
        {
            try
            {
                var user = userBLO.Find(id);
                if (user == null)
                {
                    return HttpNotFound();
                }
                var roles = roleBLO.ToList();
                ViewBag.RoleId = new SelectList(roles, "RoleId", "Name", user.RoleId);
                return View(user);
            }
            catch (Exception)
            {
                // Write to log file.
                return RedirectToAction("Index", "Error", new { Area = "" });
            }
        }

        //
        // POST: /User/Edit

        [HttpPost]
        public ActionResult Edit(User user)
        {
            try
            {
                var roles = roleBLO.ToList();
                ViewBag.RoleId = new SelectList(roles, "RoleId", "Name", user.RoleId);

                if (ModelState.IsValid)
                {
                    var picture = Request.Files["FileUpload"];
                    if (picture.ContentLength > 0)
                    {
                        var extension = picture.FileName.Split('.');
                        var nameOfPicture = user.Username + "." + extension[extension.Length - 1];
                        user.ImageUrl = nameOfPicture;
                        picture.SaveAs(HttpContext.Server.MapPath("~/Images/Profile/") + nameOfPicture);
                    }

                    // Modify User
                    var result = userBLO.Modify(user);

                    // Checking result Modify
                    switch (result)
                    {
                        // Has some one change before
                        case -1:
                            TempData["Msg"] = "The user data is out of date. Update unsuccessful.";
                            return RedirectToAction("Details", new { id = user.UserId });

                        // Duplicate E-mail
                        case -3:
                            ModelState.AddModelError("", "Duplicate E-Mail.");
                            return View(user);
                    }

                    // Update Successfully
                    if (result > 0)
                    {
                        TempData["Msg"] = "The user has been updated.";
                        return RedirectToAction("Details", new { id = user.UserId });
                    }

                    // Error
                    ModelState.AddModelError("", "Website has encountered a problem. Please try again!");
                }

                return View(user);
            }
            catch (Exception)
            {
                return RedirectToAction("Index", "Error", new { Area = "" });
            }
        }

        //
        // GET: /User/Details

        public ActionResult Details(int id = 0)
        {
            try
            {
                var user = userBLO.Find(id);
                if (user == null)
                {
                    return HttpNotFound();
                }

                //Send message to views. The message passed by some action.
                ViewBag.Msg = TempData["Msg"] as string;
                return View(user);
            }
            catch (Exception)
            {
                // Write to log file.
                return RedirectToAction("Index", "Error", new { Area = "" });
            }
        }

        //
        // GET: /User/Deactivate

        public string Deactivate(string ids = "")
        {
            try
            {
                var result = userBLO.Deactivate(ids);
                if (result > 0)
                {
                    return result + " user(s) has been deactivated.";
                }
                return "Website has encountered a problem. Please try again!";
            }
            catch (Exception)
            {
                return "Website has encountered a problem. Please try again!";
            }
        }

        //
        // GET: /User/Activate

        public string Activate(string ids = "")
        {
            try
            {
                var result = userBLO.Activate(ids);
                if (result > 0)
                {
                    return result + " user(s) has been activated.";
                }
                return "Website has encountered a problem. Please try again!";
            }
            catch (Exception)
            {
                return "Website has encountered a problem. Please try again!";
            }
        }

        //
        // Get: /User/DownloadFile

        public ActionResult Download()
        {
            return new DownloadModel
                {
                    VirtualPath = "~/ResourceFiles/Template/Template_ImportUsers.xlsx",
                    FileDownLoadName = "Template_ImportUsers.xlsx"
                };
        }

        //
        // Get: /User/Result

        public ActionResult ImportResult()
        {
            if (Session["ListUser"] != null)
            {
                var listUser = (List<UserErrorModel>) Session["ListUser"];
                ViewBag.ListUser = listUser;
            }
            if (Session["numSuccess"] != null)
            {
                var num = (int) Session["numSuccess"];
                ViewBag.Success = num;
            }
            if (Session["numFail"] != null)
            {
                var num = (int) Session["numFail"];
                ViewBag.Fail = num;
            }

            return View();
        }

        // 
        // Get: /User/Delete

        public string Delete(string ids)
        {
            try
            {
                var result = userBLO.Remove(ids);
                if (result > 0)
                {
                    return result + " user(s) has been deleted.";
                }
                return "Website has encountered a problem. Please try again!";
            }
            catch (Exception)
            {
                return "Website has encountered a problem. Please try again!";
            }
        }
    }
}
